/*
 * Project 2 - Process Scheduler
 * Team - BitwiseGuys
 * Team members: Tyson Lewis, Josh Warner, Dallas Rosson, Ken Norton
 */

package backend;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;

import backend.IO.IOType;
import backend.SchedulerProcess.ProcessType;

public class Loader {
	
	/**
	 * The maximum number of steps that a process will run before returning to zero.
	 */
	private static final int MAX_STEPS = 20;
	
	/**
	 * The minimum number of steps that a process will run.
	 */
	private static final int MIN_STEPS = 10;
	
	/**
	 * The maximum number of requests that the process can make.
	 */
	private static final int MAX_REQUESTS = 4;

	/**
	 * The array of processes.
	 */
	private SchedulerProcess my_processes[];
	
	/**
	 * The array of PCB.
	 */
	private PCB my_pcbs[];
	
	/**
	 * Main constructor for Loader.
	 * 
	 * @param the_cpu The cpu for this run.
	 */
	public Loader(final List<String> the_list) {
		createProcesses(the_list);
		createPCBList();
	}
	
	/**
	 * Creates the process list.
	 * 
	 * @param the_list The list of string names of the processes.
	 * @param the_memory The SharedMemory for the current instance of the Cpu.
	 */
	private void createProcesses(final List<String> the_list) {
		ArrayList<String> list = (ArrayList<String>) the_list;
		my_processes = new SchedulerProcess[list.size()];
		
		Random rand = new Random();
		Random rand_requests = new Random();
		
		String temp;
		IOType types[] = IOType.values();
		
		
		int count = list.size();
		for (int i = 0; i < count; i++) {
			ProcessType process_type = ProcessType.CALCULATOR;
			int no_steps = -1;
			
			temp = list.remove(0).toLowerCase();
			if (temp.equals(ProcessType.UI.toString().toLowerCase())) {
				process_type = ProcessType.UI;
			} else if (temp.equals(ProcessType.PRODUCER.toString().toLowerCase())) {
				process_type = ProcessType.PRODUCER;
			} else if (temp.equals(ProcessType.CONSUMER.toString().toLowerCase())) {
				process_type = ProcessType.CONSUMER;
			} else if (temp.equals(ProcessType.SYNCHED.toString().toLowerCase())) {
				process_type = ProcessType.SYNCHED;
			} else if (temp.equals(ProcessType.CALCULATOR.toString().toLowerCase())) {
				process_type = ProcessType.CALCULATOR;
			}
			
			do {
				no_steps = rand.nextInt(MAX_STEPS + 1);
			} while (no_steps < MIN_STEPS);
			
			int no_requests = rand.nextInt(MAX_REQUESTS + 1);
			
			int request_steps[] = new int[no_requests];
			IOType requests[] = new IOType[no_requests];
			
			for (int j = 0; j < no_requests; j++) {
				requests[j] = types[rand_requests.nextInt(types.length)];
			}
			
			for (int k = 0; k < no_requests; k++) {
				int step;
				do {
					step = rand.nextInt(no_steps);
				} while (no_steps < MIN_STEPS);
				request_steps[k] = step;
			}
			
			Arrays.sort(request_steps);
			
			my_processes[i] = new SchedulerProcess(process_type, no_steps,
					requests, request_steps);
		}
	}
	
	/**
	 * Creates the list of the PCBs from the processes.
	 */
	private void createPCBList() {
		my_pcbs = new PCB[my_processes.length];
		for (int i = 0; i < my_processes.length; i++) {
			my_pcbs[i] = new PCB(i, my_processes[i]);
		}
	}
	
	/* *********************************************************
	 * Getters
	 ***********************************************************/
	
	/**
	 * Gets a copy of the processes array.
	 * 
	 * @return The processes.
	 */
	public SchedulerProcess[] getProcessArray() {
		SchedulerProcess processes[] = new SchedulerProcess[my_processes.length];
		System.arraycopy(my_processes, 0, processes, 0, my_processes.length);
		return processes;
	}
	
	/**
	 * Gets the pcb array.
	 * 
	 * @return The PCBs.
	 */
	public PCB[] getPCBArray() {
		return my_pcbs;
	}
}
